package com.koron.tool.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.koron.bean.base.Response;
import com.koron.bean.system.staff.vo.EamUser;
import com.koron.bean.util.UUIDUtils;
import com.koron.tool.bean.*;
import com.koron.tool.enums.InventoryCycleEnum;
import com.koron.tool.enums.WarningReasonEnum;
import com.koron.tool.mapper.ToolAccountStatisticsMapper;
import com.koron.tool.mapper.ToolInventoryMapper;
import com.koron.tool.mapper.ToolWarningInfoMapper;
import com.koron.tool.service.ToolInventoryService;
import com.koron.tool.util.BeanUtil;
import com.koron.tool.util.ToolConstant;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.koron.ebs.mybatis.SessionFactory;
import org.koron.ebs.mybatis.TaskAnnotation;
import org.springframework.stereotype.Service;

import java.text.DecimalFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: laiguangming
 * @Date: 2022/10/8 10:22
 */
@Slf4j
@Service
public class ToolInventoryServiceImpl implements ToolInventoryService {

    private static final int MAX_INVENTORY_COUNT_PER_DAY = 999;

    private static final String TRIPLE_ZERO = "000";

    @Override
    @TaskAnnotation("getInventoryStatus")
    public Response getInventoryStatus(SessionFactory sessionFactory, ToolInventoryQuery toolInventoryQuery) {
        try {
            ToolInventoryMapper mapper = sessionFactory.getMapper(ToolInventoryMapper.class);
            PageHelper.startPage(toolInventoryQuery.getPage(), toolInventoryQuery.getPageSize());
            List<WarehouseInventoryBean> inventoryStatusList = mapper.getInventoryStatus(toolInventoryQuery);
            PageInfo pageInfo = new PageInfo(inventoryStatusList);
            return Response.ok(pageInfo);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Response.fail();
        }

    }

    @Override
    @TaskAnnotation("switchInventoryPreparation")
    public Response switchInventoryPreparation(SessionFactory sessionFactory, EamUser user, WarehouseInventoryBean bean) {
        try {
            if (bean.getWarehouseId() == null) {
                return Response.fail("库房id不能为空");
            }
            if (bean.getInventoryPreparation() == null) {
                return Response.fail("盘点准备状态不能为空");
            }
            if (!Objects.equals(bean.getInventoryPreparation(), ToolConstant.INVENTORY_PREPARATION_YES) &&
                    !Objects.equals(bean.getInventoryPreparation(), ToolConstant.INVENTORY_PREPARATION_NO)) {
                return Response.fail("盘点准备状态参数不合法");
            }
            BeanUtil.update(user, bean);
            ToolInventoryMapper mapper = sessionFactory.getMapper(ToolInventoryMapper.class);
            Integer value = mapper.switchInventoryPreparation(bean);
            // 取消盘点后的执行逻辑
            if (Objects.equals(bean.getInventoryPreparation(), ToolConstant.INVENTORY_PREPARATION_NO)) {
                String inventoryId = mapper.getUnfinishedInventoryId(bean.getWarehouseId());
                // 删除未盘点完的盘点单临时清单
                mapper.deleteInventoryCheckListTmp(inventoryId);
                // 删除未盘点完的盘点单盘点情况清单
                mapper.deleteInventoryCheckList(inventoryId);
                // 删除未盘点完的盘点单
                mapper.deleteInventory(bean.getWarehouseId());
            }
            return Response.ok(value);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Response.fail();
        }
    }

    @Override
    @TaskAnnotation("createInventory")
    public Response createInventory(SessionFactory sessionFactory, EamUser user, ToolInventoryBean bean) {
        try {
            ToolInventoryMapper toolInventoryMapper = sessionFactory.getMapper(ToolInventoryMapper.class);
            if (toolInventoryMapper.getInventoryPreparation(bean.getWarehouseId()) != ToolConstant.INVENTORY_PREPARATION_YES) {
                return Response.fail("当前库房未处于盘点准备状态");
            }
            if (toolInventoryMapper.getUnfinishedInventoryCount(bean.getWarehouseId()) != 0) {
                return Response.fail("当前库房已存在处于盘点状态中的盘点单");
            }
            BeanUtil.add(user, bean);
            //---------------------------------------------------------
            // 设置盘点单单号
            LocalDate now = LocalDate.now();
            String latestCode = toolInventoryMapper.getLatestCodeInCheckList();
            DateTimeFormatter yyyyMMdd = DateTimeFormatter.ofPattern("yyyyMMdd");
            String latestCodeSuffix = null;
            if (latestCode == null || LocalDate.parse(latestCode.substring(1,9), yyyyMMdd).isBefore(now)) {
                latestCodeSuffix  = TRIPLE_ZERO;
            } else {
                latestCodeSuffix = latestCode.substring(9);
            }
            int suffix = Integer.parseInt(latestCodeSuffix) + 1;
            if (suffix > MAX_INVENTORY_COUNT_PER_DAY) {
                return Response.fail("今日已创建过多盘点单");
            }
            String code = "Y" + now.format(yyyyMMdd) + new DecimalFormat(TRIPLE_ZERO).format(suffix);
            bean.setCode(code);
            //---------------------------------------------------------
            bean.setStartTime(System.currentTimeMillis() / 1000L);
            // 设置工具数量
            ToolAccountStatisticsMapper toolAccountStatisticsMapper = sessionFactory.getMapper(ToolAccountStatisticsMapper.class);
            ToolStatisticsQuery toolStatisticsQuery = new ToolStatisticsQuery();
            toolStatisticsQuery.setWarehouseId(bean.getWarehouseId());
            Long warehouseCount = toolAccountStatisticsMapper.getWarehouseCount(toolStatisticsQuery);
            bean.setTotalTools(warehouseCount);
            // 设置盘点数量
            bean.setTotalInventory(0L);
            // 设置盘点状态
            bean.setStatus(ToolConstant.INVENTORY_STATUS_UNFINISHED);
            // 创建盘点单
            toolInventoryMapper.createInventory(bean);
            return Response.ok(bean);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Response.fail();
        }
    }

    @Override
    @TaskAnnotation("getHistoricalRecords")
    public Response getHistoricalRecords(SessionFactory sessionFactory, ToolInventoryQuery query) {
        try {
            if (StringUtils.isEmpty(query.getWarehouseId())) {
                return Response.fail("库房id不能为空");
            }
            ToolInventoryMapper mapper = sessionFactory.getMapper(ToolInventoryMapper.class);
            PageHelper.startPage(query.getPage(), query.getPageSize());
            List<ToolInventoryBean> historicalRecords = mapper.getHistoricalRecords(query.getWarehouseId());
            PageInfo pageInfo = new PageInfo(historicalRecords);
            return Response.ok(pageInfo);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Response.fail();
        }
    }

    @Override
    @TaskAnnotation("configureInventoryCycle")
    public Response configureInventoryCycle(SessionFactory sessionFactory, WarehouseInventoryBean bean) {
        try {
            if (StringUtils.isEmpty(bean.getWarehouseId())) {
                return Response.fail("库房id不能为空");
            }
            if (bean.getInventoryStartDate() == null) {
                return Response.fail("盘点时间不能为空");
            }
            if (bean.getInventoryCycle() == null) {
                return Response.fail("盘点周期不能为空");
            }
            // 判断盘点周期值的合法性
            if (!InventoryCycleEnum.getMap().keySet().contains(bean.getInventoryCycle())) {
                return Response.fail("盘点周期不合法");
            }
            ToolInventoryMapper mapper = sessionFactory.getMapper(ToolInventoryMapper.class);
            Integer value = mapper.updateInventoryCycle(bean);
            return Response.ok(value);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Response.fail();
        }
    }

    @Override
    @TaskAnnotation("getInventoryList")
    public Response getInventoryList(SessionFactory sessionFactory, ToolInventoryQuery query) {
        try {
            ToolInventoryMapper mapper = sessionFactory.getMapper(ToolInventoryMapper.class);
            PageHelper.startPage(query.getPage(), query.getPageSize());
            List<ToolInventoryBean> inventoryRecords = mapper.getInventoryList(query);
            PageInfo pageInfo = new PageInfo(inventoryRecords);
            return Response.ok(pageInfo);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Response.fail();
        }
    }

    @Override
    @TaskAnnotation("cancelInventory")
    public Response cancelInventory(SessionFactory sessionFactory, ToolInventoryQuery query) {
        try {
            String inventoryId = query.getInventoryId();
            if (StringUtils.isEmpty(inventoryId)) {
                return Response.fail("盘点单id不能为空");
            }
            ToolInventoryMapper mapper = sessionFactory.getMapper(ToolInventoryMapper.class);
            ToolInventoryBean inventoryBean = mapper.getInventoryById(inventoryId);
            if (inventoryBean == null) {
                return Response.fail("不存在此盘点单");
            }
            if (inventoryBean.getStatus() != ToolConstant.INVENTORY_STATUS_UNFINISHED) {
                return Response.fail("禁止删除非盘点中状态的盘点单");
            }
            // 删除未盘点完的盘点单临时清单
            mapper.deleteInventoryCheckListTmp(inventoryId);
            // 删除未盘点完的盘点单盘点情况清单
            mapper.deleteInventoryCheckList(inventoryId);
            // 删除未盘点完的盘点单
            Integer value = mapper.deleteInventoryById(inventoryId);
            return Response.ok(value);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Response.fail();
        }
    }

    @Override
    @TaskAnnotation("insertInventoryCheckListTmp")
    public Response insertInventoryCheckListTmp(SessionFactory sessionFactory, EamUser user, List<String> RFIDs) {
        try {
            if (CollectionUtils.isEmpty(RFIDs)) {
                return Response.fail("RFIDs列表为空");
            }
            ToolInventoryMapper mapper = sessionFactory.getMapper(ToolInventoryMapper.class);
            // 根据 RFIDs 查询工器具的基本信息，并注入到 ToolInventoryCheckListTmpBean 的对应属性中
            List<ToolInventoryCheckListTmpBean> inventoryCheckListTmp = mapper.getInventoryCheckListTmp(RFIDs);
            if (CollectionUtils.isEmpty(inventoryCheckListTmp)) {
                return Response.fail("数据库中不存在RFIDs列表中所对应的工器具");
            }
            // 总盘点数量
            Integer totalInventory = 0;
            // 是否存在盘点中状态的盘点单 标志位
            boolean inventorySituationFlag = false;
            // 获取盘点人员和盘点时间
            ToolStaffNameBean toolStaffNameBean = mapper.getToolStaffName();
            // 根据库房id对扫描枪带出来的数据进行分组
            Map<String, List<ToolInventoryCheckListTmpBean>> inventoryCheckListTmpGroups = inventoryCheckListTmp.stream().collect(Collectors.groupingBy(ToolInventoryCheckListTmpBean::getWarehouseId));
            for (Map.Entry<String, List<ToolInventoryCheckListTmpBean>> entry : inventoryCheckListTmpGroups.entrySet()) {
                String warehouseId = entry.getKey();
                // 即将要插入库房（warehouseId）中的工器具列表
                List<ToolInventoryCheckListTmpBean> inventoryCheckListTmpGroup = entry.getValue();
                // 查询盘点中状态的盘点单id
                String inventoryId = mapper.getUnfinishedInventoryId(warehouseId);
                if (inventoryId == null) {
                    continue;
                }
                inventorySituationFlag = true;
                // 获取盘点单临时清单和盘点单对比情况清单中的code合集
                Set<String> codes = mapper.getCodesInCheckList(inventoryId);
                Iterator<ToolInventoryCheckListTmpBean> iterator = inventoryCheckListTmpGroup.iterator();
                while (iterator.hasNext()) {
                    ToolInventoryCheckListTmpBean tmp = iterator.next();
                    if (codes.contains(tmp.getCode())) {
                        // 删除集合中盘点单临时清单或盘点单对比情况清单中已存在的工器具，避免因重复扫描导致数据重复插入
                        iterator.remove();
                    } else {
                        BeanUtil.add(user, tmp);
                        tmp.setInventoryPerson(toolStaffNameBean.getUser());
                        tmp.setInventoryTime(toolStaffNameBean.getTime());
                        tmp.setInventoryId(inventoryId);
                    }
                }
                Integer value = 0;
                if (CollectionUtils.isNotEmpty(inventoryCheckListTmpGroup)) {
                    // 向盘点单零时清单中插入数据
                    value = mapper.insertInventoryCheckListTmp(inventoryCheckListTmpGroup);
                    totalInventory += value;
                    // 修改盘点单的盘点数量
                    mapper.updateTotalInventory(inventoryId, value);
                }

            }
            if (!inventorySituationFlag) {
                return Response.fail("当前库房下不存在盘点中状态的盘点单");
            }
            return Response.ok(totalInventory);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Response.fail();
        }
    }

    @Override
    @TaskAnnotation("getInventoryDetail")
    public Response getInventoryDetail(SessionFactory sessionFactory, ToolInventoryCheckListQuery query, Integer operation) {
        try {
            if (StringUtils.isEmpty(query.getInventoryId())) {
                return Response.fail("盘点单id不能为空");
            }
            ToolInventoryMapper mapper = sessionFactory.getMapper(ToolInventoryMapper.class);
//            PageHelper.startPage(query.getPage(), query.getPageSize());
            // 获取盘点单盘点情况清单信息
            List<ToolInventoryCheckListBean> inventoryDetail = mapper.getInventoryDetail(query);
            // 如果是盘点状态中的盘点单，还要获取盘点单临时清单信息
            if (operation == null || operation == 0) {
                List<ToolInventoryCheckListTmpBean> inventoryDetailTmp = mapper.getInventoryDetailTmp(query);
                Set<String> set = new HashSet<>();
                inventoryDetail.forEach(detail -> {
                    set.add(detail.getCode());
                });
                inventoryDetailTmp.forEach(tmpBean -> {
                    if (! set.contains(tmpBean.getCode())) {
                        inventoryDetail.add(new ToolInventoryCheckListBean(tmpBean));
                    }
                });
            }
            return Response.ok(inventoryDetail);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Response.fail();
        }
    }

    @Override
    @TaskAnnotation("saveInventory")
    public Response saveInventory(SessionFactory sessionFactory, EamUser user, String inventoryId) {
        try {
            if (StringUtils.isEmpty(inventoryId)) {
                return Response.fail("盘点单id不能为空");
            }
            ToolInventoryMapper mapper = sessionFactory.getMapper(ToolInventoryMapper.class);
            // 批量向盘点单清单中插入数据
            ToolInventoryCheckListQuery query = new ToolInventoryCheckListQuery();
            query.setInventoryId(inventoryId);
            List<ToolInventoryCheckListTmpBean> checkListTmpBeanList = mapper.getInventoryDetailTmp(query);
            Integer value = 0;
            if (!CollectionUtils.isEmpty(checkListTmpBeanList)) {
                List<ToolInventoryCheckListBean> checkListBeanList = new ArrayList<>();
                checkListTmpBeanList.forEach(tmpBean -> {
                    BeanUtil.add(user, tmpBean);
                    ToolInventoryCheckListBean bean = new ToolInventoryCheckListBean(tmpBean);
                    bean.setEndStatus(ToolConstant.INVENTORY_STATUS_IN);
                    checkListBeanList.add(bean);
                });
                value = mapper.batchSaveInventoryDetail(checkListBeanList);
                // 删除盘点单临时清单中的数据
                mapper.deleteInventoryCheckListTmp(inventoryId);
            }
            return Response.ok(value);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Response.fail();
        }
    }

    @Override
    @TaskAnnotation("getInventoryCheckDetail")
    public Response getInventoryCheckDetail(SessionFactory sessionFactory, ToolInventoryCheckListQuery query) {
        try {
            if (StringUtils.isEmpty(query.getInventoryId())) {
                return Response.fail("盘点单id不能为空");
            }
            ToolInventoryMapper mapper = sessionFactory.getMapper(ToolInventoryMapper.class);
            // 查询RFID扫描枪扫到的在库工器具
            List<ToolInventoryCheckListBean> inventoryCheckListBeans = mapper.getInventoryDetail(query);
            if (CollectionUtils.isEmpty(inventoryCheckListBeans)) {
                return Response.ok(new ArrayList<>());
            }
            inventoryCheckListBeans.forEach(bean -> {
                bean.setInventorySituation(ToolConstant.INVENTORY_SITUATION_DO);
            });
            List<String> inventoryCheckListCodes = inventoryCheckListBeans.stream().map(ToolInventoryCheckListBean::getCode).collect(Collectors.toList());
            query.setWarehouseId(inventoryCheckListBeans.get(0).getWarehouseId());
            query.setExcludeCodes(inventoryCheckListCodes);
            // 查询RFID扫描枪没扫到的但是系统显示在库的工器具
            List<ToolInventoryCheckListBean> otherInventoryDetail = mapper.getOtherInventoryDetail(query);
            if (!CollectionUtils.isEmpty(otherInventoryDetail)) {
                // 查询盘点中状态的盘点单id
                String inventoryId = mapper.getUnfinishedInventoryId(otherInventoryDetail.get(0).getWarehouseId());
                otherInventoryDetail.forEach(detail -> {
                    detail.setEndStatus(ToolConstant.INVENTORY_STATUS_OUT);
                    detail.setInventoryId(inventoryId);
                    detail.setInventorySituation(ToolConstant.INVENTORY_SITUATION_UNDO);
                    inventoryCheckListBeans.add(detail);
                });
            }
            return Response.ok(inventoryCheckListBeans);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Response.fail();
        }
    }

    @Override
    @TaskAnnotation("confirmInventory")
    public Response confirmInventory(SessionFactory sessionFactory, EamUser user, List<ToolInventoryReportBean> beanList) {
        try {
            if (CollectionUtils.isEmpty(beanList)) {
                return Response.fail("beanList列表不能为空");
            }
            ToolInventoryMapper mapper = sessionFactory.getMapper(ToolInventoryMapper.class);
            String inventoryId = mapper.getUnfinishedInventoryId(beanList.get(0).getWarehouseId());
            if (inventoryId == null) {
                return Response.fail("当前库房不存在处于盘点中状态的盘点单");
            }

            // 更新盘点人和盘点时间
            beanList.stream()
                    .filter(bean -> ToolConstant.INVENTORY_SITUATION_DO.equals(bean.getInventorySituation()))
                    .forEach(bean -> {
                        ToolInventoryCheckListBean tmpBean = new ToolInventoryCheckListBean();
                        tmpBean.setId(bean.getId());
                        tmpBean.setInventoryPerson(bean.getInventoryPerson());
                        tmpBean.setInventoryTime(bean.getInventoryTime());
                        mapper.updateInventoryCheckList(tmpBean);
                    });

            // 查询盘点单清单（已盘点工器具）中的工器具编码的集合
            Set<String> codes = mapper.getCodesAlreadyInventory(inventoryId);

            beanList.forEach(bean -> {
                BeanUtil.add(user, bean);
                // 设置盘点情况（已盘点/未盘点）
                if (codes.contains(bean.getCode())) {
                    bean.setInventorySituation(ToolConstant.INVENTORY_SITUATION_DO);
                } else {
                    bean.setInventorySituation(ToolConstant.INVENTORY_SITUATION_UNDO);
                }
/*
                if (ToolConstant.INVENTORY_STATUS_IN.equals(bean.getStartStatus())
                        && ToolConstant.INVENTORY_STATUS_OUT.equals(bean.getEndStatus())) {
                    bean.setInventorySituation(ToolConstant.INVENTORY_SITUATION_UNDO);
                } else {
                    bean.setInventorySituation(ToolConstant.INVENTORY_SITUATION_DO);
                }
*/
            });
            // 插入盘点报告单清单
            Integer value = mapper.batchInsertInventoryReport(beanList);
            // 更新更新盘点结束时间和盘点单盘点状态
            ToolInventoryBean toolInventoryBean = new ToolInventoryBean();
            toolInventoryBean.setId(beanList.get(0).getInventoryId());
            toolInventoryBean.setEndTime(System.currentTimeMillis() / 1000L);
            toolInventoryBean.setStatus(ToolConstant.INVENTORY_STATUS_FINISHED);
            mapper.updateInventory(toolInventoryBean);
            // 过滤出需要更新工器具库存状态的工器具
            Set<String> set = new HashSet<>();
            beanList.forEach(bean -> {
                if (! StringUtils.equals(bean.getStartStatus(), bean.getEndStatus())) {
                    set.add(bean.getCode());
                }
            });
            if (! set.isEmpty()) {
                // 更新工器具库存状态
                mapper.updateToolInventoryStatus(set);
                // 生成盘点账物不符预警信息
                ToolWarningInfoMapper toolWarningInfoMapper = sessionFactory.getMapper(ToolWarningInfoMapper.class);
                List<ToolWarningInfoBean> warningInfoList = toolWarningInfoMapper.getInventoryWarningInfo(set);
                warningInfoList.forEach(bean -> {
                    bean.setId(UUIDUtils.getUuid());
                    bean.setDate(System.currentTimeMillis() / 1000L);
                    bean.setReason(WarningReasonEnum.INCONSISTENT_INVENTORY.getReason());
                    bean.setStatus(ToolConstant.WARNING_INFO_STATUS_DISPLAY);
                });
                toolWarningInfoMapper.batchInsertWarningInfo(warningInfoList);
            }
            return Response.ok(value);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Response.fail();
        }
    }

    @Override
    @TaskAnnotation("getInventoryReport")
    public Response getInventoryReport(SessionFactory sessionFactory, String inventoryId) {
        try {
            if (StringUtils.isEmpty(inventoryId)) {
                return Response.fail("盘点单id不能为空");
            }
            ToolInventoryMapper mapper = sessionFactory.getMapper(ToolInventoryMapper.class);
            ToolInventoryBean toolInventoryBean = mapper.getInventoryById(inventoryId);
            List<ToolInventoryReportBean> inventoryReportBeanList = mapper.getInventoryReport(inventoryId);
            toolInventoryBean.setInventoryReportBeanList(inventoryReportBeanList);
            return Response.ok(toolInventoryBean);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Response.fail();
        }
    }
}
